/*
 * Copyright 2002-2010 Edward L. Stauff.                  Contact: <EdStauff@gmail.com>.
 * 
 * This file, "TextWriterProgressReporter.cs", is part of the "Stauffware.Common" 
 * library.
 * "Stauffware.Common" is free software: you can redistribute it and/or 
 * modify it under the terms of the GNU Lesser Public License as published by the 
 * Free Software Foundation, either version 3 of the License, or (at your option) 
 * any later version.
 * 
 * "Stauffware.Common" is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser Public License for more 
 * details.
 * 
 * You should have received a copy of the GNU Lesser Public License along with 
 * the "Stauffware.Common" sources.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Stauffware.Common.Core
{
	/// <summary>
	/// Progress reporter that writes to a TextWriter.
	/// </summary>
	public class TextWriterProgressReporter : IProgressReporter
	{
		private readonly TextWriter TextWriter;

		/// <summary>
		/// Constructs a progress reporter that writes to a TextWriter.
		/// </summary>
		/// <param name="tw">the TextWriter to which output will be written</param>
		public TextWriterProgressReporter(TextWriter tw)
		{
			Require.NotNull(tw);
			this.TextWriter = tw;
		}

		/// <see cref="Stauffware.Common.Core.IProgressReporter.ErrorCount"/> 
		public int ErrorCount
		{
			get { return this._errorCount; }
			set { this._errorCount = value; }
		}
		private int _errorCount = 0;

		/// <see cref="Stauffware.Common.Core.IProgressReporter.WarningCount"/> 
		public int WarningCount
		{
			get { return this._warningCount; }
			set { this._warningCount = value; }
		}
		private int _warningCount = 0;

		/// <summary>
		/// Suppresses all output except errors and warnings.
		/// </summary>
		public bool Terse = false;

		/// <summary>
		/// Specifies the maximum number of errors to report before exiting the program.
		/// </summary>
		public int MaxErrors = int.MaxValue;

		/// <summary>
		/// Specifies the exit code to return when the maximum number of errors has been reached.
		/// </summary>
		public int MaxErrorsExitCode = -1;

		/// <see cref="Stauffware.Common.Core.IProgressReporter.LogError"/> 
		public virtual void LogError (string descr)
		{
			this._errorCount++;
			this.TextWriter.WriteLine("*** ERROR: " + descr);
			this.TextWriter.WriteLine();
			if (this._errorCount >= this.MaxErrors)
#if SILVERLIGHT
				throw new QuitApplicationException();
#else
				Environment.Exit(this.MaxErrorsExitCode);
#endif
		}

		/// <see cref="Stauffware.Common.Core.IProgressReporter.LogWarning"/> 
		public virtual void LogWarning (string descr)
		{
			this._errorCount++;
			this.TextWriter.WriteLine("* WARNING: " + descr);
		}

		/// <see cref="Stauffware.Common.Core.IProgressReporter.LogException(Exception)"/> 
		public virtual void LogException (Exception exc)
		{
			this._errorCount++;
			this.TextWriter.Write("*** ");
			for (Exception x = exc; x != null; x = x.InnerException)
				this.TextWriter.WriteLine(x.ToString());
			this.TextWriter.WriteLine();
			if (this._errorCount >= this.MaxErrors)
#if SILVERLIGHT
				throw new QuitApplicationException();
#else
				Environment.Exit(this.MaxErrorsExitCode);
#endif
		}

		/// <see cref="Stauffware.Common.Core.IProgressReporter.LogException(Exception, string)"/> 
		public virtual void LogException (Exception exc, string context)
		{
			this._errorCount++;
			this.TextWriter.Write("*** " + context + " - ");
			for (Exception x = exc; x != null; x = x.InnerException)
				this.TextWriter.WriteLine(x.ToString());
			this.TextWriter.WriteLine();
			if (this._errorCount >= this.MaxErrors)
#if SILVERLIGHT
				throw new QuitApplicationException();
#else
				Environment.Exit(this.MaxErrorsExitCode);
#endif
		}

		/// <see cref="Stauffware.Common.Core.IProgressReporter.LogLine"/> 
		public virtual void LogLine (string descr)
		{
			if (!this.Terse)
				this.TextWriter.WriteLine(descr);
		}

		/// <see cref="Stauffware.Common.Core.IProgressReporter.Log"/> 
		public virtual void Log (string text)
		{
			if (!this.Terse)
				this.TextWriter.Write(text);
		}

		/// <see cref="Stauffware.Common.Core.IProgressReporter.Indent"/> 
		public virtual void Indent () { }

		/// <see cref="Stauffware.Common.Core.IProgressReporter.Outdent"/> 
		public virtual void Outdent () { }

		/// <see cref="Stauffware.Common.Core.IProgressReporter.OutdentAll"/> 
		public virtual void OutdentAll () { }

		/// <see cref="Stauffware.Common.Core.IProgressReporter.Clear"/> 
		public virtual void Clear () { }
	}
}
